package com.forexample.myapplication

import android.app.Service
import android.content.Context
import android.content.Intent
import android.graphics.ImageFormat
import android.graphics.PixelFormat
import android.hardware.camera2.*
import android.hardware.camera2.params.OutputConfiguration
import android.hardware.camera2.params.SessionConfiguration
import android.hardware.camera2.params.StreamConfigurationMap
import android.media.MediaRecorder
import android.os.Handler
import android.os.HandlerThread
import android.os.IBinder
import android.util.Log
import android.util.Size
import android.view.*
import android.view.WindowManager.LayoutParams
import android.widget.FrameLayout
import android.widget.Toast
import java.io.File
import java.util.concurrent.Executor

class CameraService : Service() {
    private var cameraManager: CameraManager? = null;
    private var cameraCharacteristics: CameraCharacteristics? = null;
    private var frontCameraId: String = ""
    private var cameraHandler: Handler? = null;
    private var handlerThread: HandlerThread? = null;

    //    private var outList: List<OutputConfiguration>? = null;
    private var myMediaRecorder: MediaRecorder? = null;
    private var myPreviewSurfView: PreviewSurfView? = null;
    private var outs: List<OutputConfiguration>? = null;
    private var myCameraDevice: CameraDevice? = null;
    private var view: View? = null;
    private var frameLayout: FrameLayout? = null;
    private var lensFacing: Int = CameraCharacteristics.LENS_FACING_FRONT
   private var windowManager:WindowManager?=null
    override fun onBind(intent: Intent?): IBinder? {
        TODO("Not yet implemented")
    }


    override fun onCreate() {
        super.onCreate()
         windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val layoutParams = LayoutParams();
        layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
        layoutParams.gravity = Gravity.LEFT and Gravity.TOP;
        layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
        layoutParams.format = PixelFormat.RGBA_8888
        layoutParams.height = 1;
        layoutParams.width =1;
        layoutParams.x = 0
        layoutParams.y = 0;
        val layoutInflater: LayoutInflater = LayoutInflater.from(this);
        view = layoutInflater.inflate(R.layout.service_main_camera, null)
        frameLayout = view!!.findViewById(R.id.fl)
        if (!view!!.isAttachedToWindow) {
            windowManager!!.addView(view, layoutParams)

        }
    }


    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        val facing = intent!!.getStringExtra("LENS_FACING")
        if (facing!!.equals("LENS_FACING_FRONT")) {
            lensFacing = CameraCharacteristics.LENS_FACING_FRONT
        } else {
            lensFacing = CameraCharacteristics.LENS_FACING_BACK

        }
        cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
        val cameraId = cameraManager!!.cameraIdList
        for (id: String in cameraId) {
            cameraCharacteristics = cameraManager!!.getCameraCharacteristics(id)


            if (cameraCharacteristics!!.get(CameraCharacteristics.LENS_FACING) == lensFacing) {
                frontCameraId = id;
            }

        }
        startMyThread()
        myPreviewSurfView = PreviewSurfView(this, surfaceHolderCall)
        frameLayout!!.addView(myPreviewSurfView)
        cameraHandler!!.postDelayed(Runnable {

            myMediaRecorder!!.prepare()
            openCamera()
        }, 4000)
        return super.onStartCommand(intent, flags, startId)

    }


    private fun startMyThread() {
        handlerThread = HandlerThread("Camera")
        handlerThread!!.start();
        cameraHandler = Handler(handlerThread!!.looper)

    }


    fun stopThread() {
        cameraHandler!!.removeCallbacksAndMessages(null)
        handlerThread!!.quitSafely()
        handlerThread!!.join()
        handlerThread = null;
        cameraHandler = null;
    }

    private fun openCamera() {

        cameraManager!!.openCamera(frontCameraId, openCameraCallback, cameraHandler)
    }

    fun startRecord() {
        Toast.makeText(this,"启动成功",Toast.LENGTH_SHORT).show()
        myMediaRecorder!!.start()
    }

    fun stopRecord() {
        myMediaRecorder!!.stop()
        myCameraDevice!!.close()
        myMediaRecorder=null;
        myCameraDevice=null
        if (view!!.isAttachedToWindow) {
            windowManager!!.removeView(view)

        }
    }

    private fun initMediaRecorder() {
        myMediaRecorder = MediaRecorder();
        myMediaRecorder!!.setVideoSource(MediaRecorder.VideoSource.SURFACE)
        myMediaRecorder!!.setAudioSource(MediaRecorder.AudioSource.MIC)
        myMediaRecorder!!.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
        myMediaRecorder!!.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
        myMediaRecorder!!.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT)
        myMediaRecorder!!.setVideoEncodingBitRate(8 * 1024 * 1920)//设置比特率 一般是 1*分辨率 到 10*分辨率 之间波动。比特率越大视频越清晰但是视频文件也越大。
        myMediaRecorder!!.setVideoFrameRate(30)//设置帧数 选择 30即可， 过大帧数也会让视频文件更大当然也会更流畅，但是没有多少实际提升。人眼极限也就30帧了。
        val size = getVideoSize();
        myMediaRecorder!!.setOrientationHint(90)
        myMediaRecorder!!.setVideoSize(size!!.width, size!!.height)
        myMediaRecorder!!.setPreviewDisplay(myPreviewSurfView!!.slf!!.surface)

        val file = File(externalCacheDir.toString() + "/" + System.currentTimeMillis() + ".mp4")

        myMediaRecorder!!.setOutputFile(file.absolutePath)


    }

    private fun getVideoSize(): Size? {

//        此相机设备支持的可用流配置;还包括最小帧持续时间和每个格式/大小组合的延迟持续时间。
//        所有相机设备将支持传感器最大分辨率
        val streamConfigurationMap: StreamConfigurationMap? =
            cameraCharacteristics!!.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
        val sizes = streamConfigurationMap!!.getOutputSizes(ImageFormat.JPEG);
        val displayMetrics = resources.displayMetrics
        val displayWidth = displayMetrics.widthPixels;
        val displayHeight = displayMetrics.widthPixels;
        /**
         * 循环40次,让宽度范围从最小逐步增加,找到最符合屏幕宽度的分辨率,
         * 你要是不放心那就增加循环,肯定会找到一个分辨率,不会出现此方法返回一个null的Size的情况
         * ,但是循环越大后获取的分辨率就越不匹配
         */
        var selectSize: Size? = null;
        for (j in 1..40) {
            for (size: Size in sizes) {
                //判断当前Size高度小于屏幕宽度+j*5  &&  判断当前Size高度大于屏幕宽度-j*5  &&  判断当前Size宽度小于当前屏幕高度
                if (size.height < displayWidth + j * 5 && size.height > displayWidth - j * 5) {
                    if (selectSize != null) { //如果之前已经找到一个匹配的宽度
                        if (Math.abs(displayHeight - selectSize.width) < Math.abs(displayHeight - selectSize.getWidth())) { //求绝对值算出最接近设备高度的尺寸
                            selectSize = size
                            continue
                        }
                    } else {
                        selectSize = size
                    }
                }
            }
        }
        return selectSize;
    }

    private val openCameraCallback: CameraDevice.StateCallback =
        object : CameraDevice.StateCallback() {
            override fun onOpened(cameraDevice: CameraDevice) {
                if (outs == null) {
                    outs = arrayListOf(
                        OutputConfiguration(myPreviewSurfView!!.slf!!.surface),
                        OutputConfiguration(myMediaRecorder!!.surface)
                    )
                }
                myCameraDevice = cameraDevice;
                myCameraDevice!!.createCaptureSession(
                    SessionConfiguration(
                        SessionConfiguration.SESSION_REGULAR,
                        outs!!,
                        executor,
                        sessionCallback
                    )
                )
            }

            override fun onDisconnected(camera: CameraDevice) {
                var camera = camera

            }

            override fun onError(camera: CameraDevice, error: Int) {

                var camera = camera
                camera.close()
            }
        }
    private val surfaceHolderCall: SurfaceHolder.Callback = object : SurfaceHolder.Callback {
        override fun surfaceCreated(holder: SurfaceHolder) {
            initMediaRecorder()


        }

        override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
        }

        override fun surfaceDestroyed(holder: SurfaceHolder) {
        }


    }
    private val executor: Executor = Executor { command -> command!!.run() }

    //会话的回调
    private val sessionCallback: CameraCaptureSession.StateCallback =
        object : CameraCaptureSession.StateCallback() {
            override fun onConfigured(session: CameraCaptureSession) {
                var build: CaptureRequest.Builder =
                    myCameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_RECORD)
                build.set(
                    CaptureRequest.CONTROL_AF_MODE,
                    CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE
                )
                build.addTarget(myPreviewSurfView!!.slf!!.surface)
                build.addTarget(myMediaRecorder!!.surface)
                session.setRepeatingRequest(build.build(), sessionCaptureCallback, cameraHandler!!)

                startRecord()

            }

            override fun onConfigureFailed(session: CameraCaptureSession) {
            }

        }
    private val sessionCaptureCallback: CameraCaptureSession.CaptureCallback =
        object : CameraCaptureSession.CaptureCallback() {

            override fun onCaptureStarted(
                session: CameraCaptureSession,
                request: CaptureRequest,
                timestamp: Long,
                frameNumber: Long
            ) {
                super.onCaptureStarted(session, request, timestamp, frameNumber)
            }

        }


    override fun onDestroy() {
        super.onDestroy()
        stopRecord()
        MainActivity.OpenServiceState.isOpen = false
    }
}